﻿namespace Summoner
{
    using UnityEngine;
    using UnityEditor;
    using System.IO;
    using System.Collections.Generic;
    using System;
    using System.Reflection;

    public class ConsolePublisher
    {
        public static string AssetConfigName = "AssetNames";
        private static BuildTargetGroup buildTargetGroup = BuildTargetGroup.iOS;
        private static BuildOptions buildOption = BuildOptions.None;

        public static void Build()
        {
            #region check build parameters
            string[] args = Environment.GetCommandLineArgs();
            buildTargetGroup = ConvertToBuildTarget<BuildTargetGroup>(args[args.Length - 2]);
            buildOption = ConvertToBuildTarget<BuildOptions>(args[args.Length - 1]);
            #endregion
            AssetVessel vessel = AssetDatabase.LoadAssetAtPath(AssetPath.AssetVesselPath, typeof(AssetVessel)) as AssetVessel;
            BuildBundle(vessel, GetSelectedBuildTarget(buildTargetGroup));
            Build(buildTargetGroup);
        }

        private static void BuildBundle(AssetVessel vessel, BuildTarget buildTarget)
        {
            BundleFunction.GenerateAssetBundle(vessel.assetList, buildTarget);
            GameConfigInfo information = new GameConfigInfo() { version = vessel.version, platform = Application.platform, language = SystemLanguage.Chinese, assets = vessel.assetList };
            JsonSerializer.PackJsonToFile(AssetPath.PublishPath, information, AssetPath.AssetConfigName.ToLower());
        }

        private static T ConvertToBuildTarget<T>(string value)
        {
            return (T)Enum.Parse(typeof(T), value);
        }

        private static string GetCurrentDate()
        {
            return DateTime.Now.Year + "-" + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + DateTime.Now.Hour + "-" + DateTime.Now.Minute + "-" + DateTime.Now.Second;
        }

        private static string GetProjectName()
        {
            string[] s = Application.dataPath.Split('/');
            return (s[s.Length - 2] + "-" + GetCurrentDate());
        }

        private static string[] GetLevelsFromBuildSettings()
        {
            List<string> levels = new List<string>();
            for (int i = 0; i < EditorBuildSettings.scenes.Length; ++i)
            {
                if (EditorBuildSettings.scenes[i].enabled)
                {
                    levels.Add(EditorBuildSettings.scenes[i].path);
                }
            }
            return levels.ToArray();
        }

        private static void Build(BuildTargetGroup buildTarget)
        {
            PlayerSettings.stripEngineCode = false;
            string[] scenes = GetLevelsFromBuildSettings();
            Directory.CreateDirectory(BuildPath());
            EditorUserBuildSettings.SwitchActiveBuildTarget(buildTarget, GetSelectedBuildTarget(buildTarget));
            switch (GetSelectedBuildTarget(buildTarget))
            {
                case BuildTarget.iOS:
                    {
                        buildOption |= BuildOptions.AcceptExternalModificationsToPlayer;
                        buildOption |= BuildOptions.Il2CPP;
                        EditorUserBuildSettings.iOSBuildConfigType = iOSBuildType.Release;
                        BuildPipeline.BuildPlayer(scenes, BuildPath() + "-" + GetCurrentDate(), GetSelectedBuildTarget(buildTarget), buildOption);
                    }
                    break;
                case BuildTarget.Android:
                    {
                        EditorUserBuildSettings.androidBuildSubtarget = MobileTextureSubtarget.Generic;
                        EditorUserBuildSettings.androidBuildType = AndroidBuildType.Release;
                        if (buildOption == BuildOptions.AcceptExternalModificationsToPlayer)
                        {
                            buildOption |= BuildOptions.AcceptExternalModificationsToPlayer;
                            buildOption |= BuildOptions.Il2CPP;
                            EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle;
                            BuildPipeline.BuildPlayer(scenes, BuildPath() + "/" + GetProjectName(), GetSelectedBuildTarget(buildTarget), buildOption);
                        }
                        else
                        {
                            buildOption |= BuildOptions.Il2CPP;
                            BuildPipeline.BuildPlayer(scenes, BuildPath() + "/" + GetProjectName() + ".apk", GetSelectedBuildTarget(buildTarget), buildOption);
                        }
                    }
                    break;
                case BuildTarget.StandaloneWindows:
                    {
                        BuildPipeline.BuildPlayer(scenes, BuildPath() + "/" + GetProjectName() + ".exe", GetSelectedBuildTarget(buildTarget), buildOption);
                    }
                    break;
                case BuildTarget.StandaloneWindows64:
                    {
                        BuildPipeline.BuildPlayer(scenes, BuildPath() + "/" + GetProjectName() + ".exe", GetSelectedBuildTarget(buildTarget), buildOption);
                    }
                    break;
                case BuildTarget.StandaloneOSXIntel:
                    {
                        BuildPipeline.BuildPlayer(scenes, BuildPath() + "/" + GetProjectName() + ".app", GetSelectedBuildTarget(buildTarget), buildOption);
                    }
                    break;
                case BuildTarget.StandaloneOSXIntel64:
                    {
                        BuildPipeline.BuildPlayer(scenes, BuildPath() + "/" + GetProjectName() + ".app", GetSelectedBuildTarget(buildTarget), buildOption);
                    }
                    break;
                case BuildTarget.StandaloneOSXUniversal:
                    {
                        BuildPipeline.BuildPlayer(scenes, BuildPath() + "/" + GetProjectName() + ".app", GetSelectedBuildTarget(buildTarget), buildOption);
                    }
                    break;
            }
            EditorApplication.Exit(0);
        }

        private static BuildTarget GetSelectedBuildTarget(BuildTargetGroup buildTargetGroup)
        {
            switch (buildTargetGroup)
            {
                case BuildTargetGroup.WebPlayer:
                    if (EditorUserBuildSettings.webPlayerStreamed)
                    {
                        return BuildTarget.WebPlayerStreamed;
                    }
                    return BuildTarget.WebPlayer;

                case BuildTargetGroup.Standalone:
                    return EditorUserBuildSettings.selectedStandaloneTarget;

                case BuildTargetGroup.iOS:
                    return BuildTarget.iOS;

                case BuildTargetGroup.Android:
                    return BuildTarget.Android;

                case BuildTargetGroup.tvOS:
                    return BuildTarget.tvOS;

                case BuildTargetGroup.Tizen:
                    return BuildTarget.Tizen;

                case BuildTargetGroup.XBOX360:
                    return BuildTarget.XBOX360;

                case BuildTargetGroup.XboxOne:
                    return BuildTarget.XboxOne;

                case BuildTargetGroup.PS3:
                    return BuildTarget.PS3;

                case BuildTargetGroup.PSP2:
                    return BuildTarget.PSP2;

                case BuildTargetGroup.PS4:
                    return BuildTarget.PS4;

                case BuildTargetGroup.WSA:
                    return BuildTarget.WSAPlayer;

                case BuildTargetGroup.WebGL:
                    return BuildTarget.WebGL;

                case BuildTargetGroup.SamsungTV:
                    return BuildTarget.SamsungTV;

                case BuildTargetGroup.Facebook:
                    PropertyInfo property = typeof(EditorUserBuildSettings).GetProperty("selectedFacebookTarget", BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic);
                    return (BuildTarget)property.GetValue(null, null);

                default:
                    return EditorUserBuildSettings.activeBuildTarget;
            }
        }

        private static string BuildPath()
        {
            switch (GetSelectedBuildTarget(buildTargetGroup))
            {
                case BuildTarget.iOS:
                    return "builds/IOS";
                case BuildTarget.Android:
                    return "builds/Android";
                case BuildTarget.StandaloneWindows:
                    return "builds/Win";
                case BuildTarget.StandaloneWindows64:
                    return "builds/Win64";
                case BuildTarget.StandaloneOSXIntel:
                    return "builds/Mac";
                case BuildTarget.StandaloneOSXIntel64:
                    return "builds/Mac64";
                case BuildTarget.StandaloneOSXUniversal:
                    return "builds/MacUniversal";
            }
            return "builds";
        }

        private static string ConfigPath
        {
            get
            {
                return Path.Combine(Application.dataPath, "AssetConfig");
            }
        }
    }
}